This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Cmd+Shift+Enter.

#import libraries
library(plyr)
library(tidyverse)
library(dplyr)
library(corrplot)
library(ggplot2)
library(ggcorrplot)
library(data.table)
data.table 1.12.2 using 2 threads (see ?getDTthreads).  Latest news: r-datatable.com

Attaching package: ‘data.table’

The following objects are masked from ‘package:dplyr’:

    between, first, last

The following object is masked from ‘package:purrr’:

    transpose
#Import dataset diemthi2019.csv
diemthi2019 <- read.csv('~/Desktop/2019 vietnam national high school exam/diemthi2019.csv', row.names = NULL)
#Choose necessary columns and reorder them
head(diemthi2019)
str(diemthi2019)
'data.frame':   811851 obs. of  12 variables:
 $ X               : int  0 1 2 3 4 5 6 7 8 9 ...
 $ Dia             : num  7.75 NA 4.25 4.75 8.25 NA NA 6.25 NA 7.5 ...
 $ GDCD            : num  8.75 NA 5.75 5 7.5 NA NA 8.75 NA 8.5 ...
 $ Hoa             : num  NA 4.5 NA NA NA 5.75 NA NA 3.5 NA ...
 $ Li              : num  NA 8.25 NA NA NA 7.5 NA NA 5.5 NA ...
 $ Ma_mon_ngoai_ngu: Factor w/ 7 levels "","N1","N2","N3",..: 2 2 1 1 2 2 1 2 2 2 ...
 $ Ngoai_ngu       : num  7.6 8 NA NA 4.4 4.4 NA 8.8 2.2 5.2 ...
 $ Sinh            : num  NA 6 NA NA NA 3 NA NA 3.75 NA ...
 $ Su              : num  8.25 NA 4 2.25 7.75 NA 3.25 5.25 NA 3.25 ...
 $ Toan            : num  8.2 8.6 5.2 4.4 5.8 7.2 2.2 5 5.6 6.6 ...
 $ Van             : num  8 6.17 4.75 4.5 6 6.75 5.75 6.5 4.5 7 ...
 $ sbd             : int  24008611 51000032 51000005 51000021 51000013 51000003 51000001 51000011 51000007 51000010 ...
#Import and modify dataset province_code.csv
province_code <- read.csv('~/Desktop/2019 vietnam national high school exam/province_code.csv', sep = ";", row.names = NULL)
#Change column type of province_code.csv
province_code$Province_code <- as.numeric(province_code$Province_code)
province_code$Province_name <- as.factor(province_code$Province_name)
head(province_code)
str(province_code)
'data.frame':   64 obs. of  2 variables:
 $ Province_code: num  1 2 3 4 5 6 7 8 9 10 ...
 $ Province_name: Factor w/ 63 levels "","An Giang",..: 24 29 27 16 22 15 35 38 60 37 ...
#Change column name for diemthi2019.csv
diemthi2019 <- plyr::rename(diemthi2019, c(
    'sbd' = 'Student_index',
    'Toan'= 'Maths',
    'Van' = 'Literature',
    'Ngoai_ngu' = 'Foreign_language',
    'Ma_mon_ngoai_ngu' = 'Foreign_language_code',
    'Li' = 'Physics',
    'Hoa' = 'Chemistry',
    'Sinh' = 'Biology',
    'Su' = 'History',
    'Dia' = 'Geography',
    'GDCD' = 'Citizenship_education'
    )
  )
head(diemthi2019)
#Insert province_code for diemthi2019.csv
Province_code <- ifelse(diemthi2019$Student_index > 10000000,
            substr(as.character(diemthi2019$Student_index), start = 1, stop = 2),
            substr(as.character(diemthi2019$Student_index), start = 1, stop = 1)
)
diemthi2019$Province_code <- as.numeric(Province_code)
#insert foreign language names with respect to code
diemthi2019$Foreign_language_name <- diemthi2019$Foreign_language_code
diemthi2019$Foreign_language_name <- mapvalues(diemthi2019$Foreign_language_code, from=c("N1", "N2", "N3", "N4", "N5", "N6"), to=c("English", "Russian", "French", "Chinese", "German", "Japanese"))
head(diemthi2019)
#Merge diemthi2019.csv and province_code.csv
diemthi2019 <- join(diemthi2019, province_code, by = "Province_code")
head(diemthi2019)
#Calculate scores of combinations A00, A01, B00, C00, D00
diemthi2019$A00 <- diemthi2019$Maths + diemthi2019$Physics + diemthi2019$Chemistry
if(diemthi2019$Foreign_language_code == 'N1') {
  diemthi2019$A01 <- diemthi2019$Maths + diemthi2019$Physics + diemthi2019$Foreign_language
}
the condition has length > 1 and only the first element will be used
diemthi2019$B00 <- diemthi2019$Maths + diemthi2019$Chemistry + diemthi2019$Biology
diemthi2019$C00 <- diemthi2019$Literature + diemthi2019$History + diemthi2019$Geography
if(diemthi2019$Foreign_language_code == 'N1') {
  diemthi2019$D00 <- diemthi2019$Maths + diemthi2019$Literature + diemthi2019$Foreign_language
}
the condition has length > 1 and only the first element will be used
head(diemthi2019)
#Calculate average of natural science combination and social science combination
diemthi2019$Avg_natural_sciences <- (diemthi2019$Physics + diemthi2019$Chemistry + diemthi2019$Biology)/3
diemthi2019$Avg_social_sciences <- (diemthi2019$History + diemthi2019$Geography + diemthi2019$Citizenship_education)/3
#Reorder and choose necessary columns
diemthi2019 <- diemthi2019[c('Student_index', 'Province_code', 'Province_name', 'Maths', 'Literature', 'Foreign_language' ,'Foreign_language_code', 'Foreign_language_name', 'Physics', 'Chemistry', 'Biology', 'Avg_natural_sciences', 'History', 'Geography', 'Citizenship_education', 'Avg_social_sciences', 'A00', 'A01', 'B00', 'C00', 'D00')]
head(diemthi2019)
#numerical df for correlation matrix
diemthi2019_corr <- diemthi2019[c(4:6,9:21)]
#correlation matrix
diemthi2019_corr_matrix <- cor(diemthi2019_corr, use="pairwise.complete.obs")
View(diemthi2019_corr_matrix)
#correlation heatmap
ggcorrplot(diemthi2019_corr_matrix, hc.order = TRUE,
   lab = TRUE)

#Number of students who takes each foreign language test
table(diemthi2019$Foreign_language_name)

          English  Russian   French  Chinese   German Japanese 
   83338   726064      148      646      801       81      773 
#Number of students who took each subject
took_subject <- list()
for(i in c(4:6, 9:11, 13:15)) {
  print(paste('The number of students who took the subject', colnames(diemthi2019[i]), 'is', sum(!is.na(diemthi2019[,i]) == TRUE))) 
}
[1] "The number of students who took the subject Maths is 807762"
[1] "The number of students who took the subject Literature is 799208"
[1] "The number of students who took the subject Foreign_language is 728513"
[1] "The number of students who took the subject Physics is 292166"
[1] "The number of students who took the subject Chemistry is 295544"
[1] "The number of students who took the subject Biology is 291199"
[1] "The number of students who took the subject History is 542729"
[1] "The number of students who took the subject Geography is 535897"
[1] "The number of students who took the subject Citizenship_education is 470905"
#Number of students who are eligible to be considered for admission with each combination A00, A01, B00, C00, D00
combination_eligible <- list()
for(i in c(17:21)) {
  print(paste('The number of students who are eligible to be considered for combination', colnames(diemthi2019[i]), 'is', sum(!is.na(diemthi2019[,i]) == TRUE))) 
  combination_eligible[[i-16]] = table(!is.na(diemthi2019[,i]), dnn = paste(colnames(diemthi2019)[i]))
}
[1] "The number of students who are eligible to be considered for combination A00 is 290759"
[1] "The number of students who are eligible to be considered for combination A01 is 281100"
[1] "The number of students who are eligible to be considered for combination B00 is 291078"
[1] "The number of students who are eligible to be considered for combination C00 is 535427"
[1] "The number of students who are eligible to be considered for combination D00 is 725824"
combination_eligible
[[1]]
A00
 FALSE   TRUE 
521092 290759 

[[2]]
A01
 FALSE   TRUE 
530751 281100 

[[3]]
B00
 FALSE   TRUE 
520773 291078 

[[4]]
C00
 FALSE   TRUE 
276424 535427 

[[5]]
D00
 FALSE   TRUE 
 86027 725824 
#Number of students who took all natural science subjects, all social science subjects, or all of both
print(paste('The number of students who took all natural science subjects is', sum(!is.na(diemthi2019[,13]) == TRUE)))
[1] "The number of students who took all natural science subjects is 542729"
print(paste('The number of students who took all social science subjects is', sum(!is.na(diemthi2019[,17]) == TRUE)))
[1] "The number of students who took all social science subjects is 290759"
print(paste('The number of students who took all natural and social science subjects is', sum(!is.na(diemthi2019[,13]) == TRUE & !is.na(diemthi2019[,17]) == TRUE)))
[1] "The number of students who took all natural and social science subjects is 30746"
#Find the maximum score for each column
for(i in c(4:6,9:21)) {
  print(paste('The maximum score of',colnames(diemthi2019)[i],'is', max(diemthi2019[,i], na.rm = TRUE)))
}
[1] "The maximum score of Maths is 10"
[1] "The maximum score of Literature is 9.5"
[1] "The maximum score of Foreign_language is 10"
[1] "The maximum score of Physics is 10"
[1] "The maximum score of Chemistry is 10"
[1] "The maximum score of Biology is 10"
[1] "The maximum score of Avg_natural_sciences is 9.41666666666667"
[1] "The maximum score of History is 10"
[1] "The maximum score of Geography is 10"
[1] "The maximum score of Citizenship_education is 10"
[1] "The maximum score of Avg_social_sciences is 9.83333333333333"
[1] "The maximum score of A00 is 29.05"
[1] "The maximum score of A01 is 28.9"
[1] "The maximum score of B00 is 29.8"
[1] "The maximum score of C00 is 28.75"
[1] "The maximum score of D00 is 28.4"
histogram_out <- list()
for(i in c(4:6,9:21)) {
  x = diemthi2019[,i]
  histogram_out[[i]] <- ggplot(data.frame(x), aes(x)) + 
    geom_histogram(binwidth = 0.1, color="black", fill="blue") +
    labs(title=paste("Score histogram for",colnames(diemthi2019)[i]), x=colnames(diemthi2019)[i], y="Count") + 
    geom_vline(data = diemthi2019, xintercept = mean(diemthi2019[,i], na.rm = TRUE), color = "red", linetype = "dashed", size = 1)
}
histogram_out
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]

[[5]]

[[6]]

[[7]]
NULL

[[8]]
NULL

[[9]]

[[10]]

[[11]]

[[12]]

[[13]]

[[14]]

[[15]]

[[16]]

[[17]]

[[18]]

[[19]]

[[20]]

[[21]]

table_score <- list()
for(i in c(4:6,9:21)) {
  table_score[[i]] = table(diemthi2019[,i], dnn = paste(colnames(diemthi2019)[i],'_scores'))
}

for(i in c(4:6,9:21)) {
  View(table_score[[i]])
}
#table_score
summary(diemthi2019[,3])
province_frequency <- table(diemthi2019[,3])
 #sort(province_frequency, decreasing = FALSE) 
province_frequency <-count(diemthi2019, Province_name)
names(province_frequency) <- c('Province', 'Frequency')
province_frequency <- province_frequency[order(-province_frequency$Frequency),]
par(las=2)
View(province_frequency)
ggplot(data=province_frequency, aes(x=reorder(Province,Frequency),y=Frequency)) +
  geom_bar(position="dodge", stat="identity") + 
  coord_flip() +
  ggtitle(paste('Barplot of number of students by province')) +
  labs(x = "Province", y = "Number of students")

barplot_mean <- list()
for(i in c(4:6,9:21)) {
  x <- aggregate(diemthi2019[,i] ~ diemthi2019$Province_name, diemthi2019, mean)
  names(x) <- c('Province', 'Mean')
  x <- x[order(x$Mean),]
  
  barplot_mean[[i]] <- ggplot(data=x, aes(x=reorder(Province,Mean),y=Mean)) +
  geom_bar(position="dodge",stat="identity") + 
  coord_flip() +
  ggtitle(paste('Barplot for mean of', colnames(diemthi2019)[i], 'by province')) + 
  labs(x = "Province", y = "Mean score")
}
barplot_mean
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]

[[5]]

[[6]]

[[7]]
NULL

[[8]]
NULL

[[9]]

[[10]]

[[11]]

[[12]]

[[13]]

[[14]]

[[15]]

[[16]]

[[17]]

[[18]]

[[19]]

[[20]]

[[21]]

LS0tCnRpdGxlOiAiMjAxOSBWaWV0bmFtIEhpZ2ggU2Nob29sIE5hdGlvbmFsIEdyYWR1YXRpb24gRXhhbSBzY29yZSBhbmFseXNpcyIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjoKICAtIG5hbWU6IEhvYW5nIEFuaCBOR08KICAtIGFmZmlsaWF0aW9uOiBFY29sZSBQb2x5dGVjaG5pcXVlLCBJUCBQYXJpcwotLS0KClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rLiBXaGVuIHlvdSBleGVjdXRlIGNvZGUgd2l0aGluIHRoZSBub3RlYm9vaywgdGhlIHJlc3VsdHMgYXBwZWFyIGJlbmVhdGggdGhlIGNvZGUuIAoKVHJ5IGV4ZWN1dGluZyB0aGlzIGNodW5rIGJ5IGNsaWNraW5nIHRoZSAqUnVuKiBidXR0b24gd2l0aGluIHRoZSBjaHVuayBvciBieSBwbGFjaW5nIHlvdXIgY3Vyc29yIGluc2lkZSBpdCBhbmQgcHJlc3NpbmcgKkNtZCtTaGlmdCtFbnRlciouIAoKCmBgYHtyfQojaW1wb3J0IGxpYnJhcmllcwpsaWJyYXJ5KHBseXIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGNvcnJwbG90KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2djb3JycGxvdCkKbGlicmFyeShkYXRhLnRhYmxlKQpgYGAKCgpgYGB7cn0KI0ltcG9ydCBkYXRhc2V0IGRpZW10aGkyMDE5LmNzdgpkaWVtdGhpMjAxOSA8LSByZWFkLmNzdignfi9EZXNrdG9wLzIwMTkgdmlldG5hbSBuYXRpb25hbCBoaWdoIHNjaG9vbCBleGFtL2RpZW10aGkyMDE5LmNzdicsIHJvdy5uYW1lcyA9IE5VTEwpCgojQ2hvb3NlIG5lY2Vzc2FyeSBjb2x1bW5zIGFuZCByZW9yZGVyIHRoZW0KaGVhZChkaWVtdGhpMjAxOSkKc3RyKGRpZW10aGkyMDE5KQoKI0ltcG9ydCBhbmQgbW9kaWZ5IGRhdGFzZXQgcHJvdmluY2VfY29kZS5jc3YKcHJvdmluY2VfY29kZSA8LSByZWFkLmNzdignfi9EZXNrdG9wLzIwMTkgdmlldG5hbSBuYXRpb25hbCBoaWdoIHNjaG9vbCBleGFtL3Byb3ZpbmNlX2NvZGUuY3N2Jywgc2VwID0gIjsiLCByb3cubmFtZXMgPSBOVUxMKQoKI0NoYW5nZSBjb2x1bW4gdHlwZSBvZiBwcm92aW5jZV9jb2RlLmNzdgpwcm92aW5jZV9jb2RlJFByb3ZpbmNlX2NvZGUgPC0gYXMubnVtZXJpYyhwcm92aW5jZV9jb2RlJFByb3ZpbmNlX2NvZGUpCnByb3ZpbmNlX2NvZGUkUHJvdmluY2VfbmFtZSA8LSBhcy5mYWN0b3IocHJvdmluY2VfY29kZSRQcm92aW5jZV9uYW1lKQoKaGVhZChwcm92aW5jZV9jb2RlKQpzdHIocHJvdmluY2VfY29kZSkKYGBgCgoKYGBge3J9CiNDaGFuZ2UgY29sdW1uIG5hbWUgZm9yIGRpZW10aGkyMDE5LmNzdgpkaWVtdGhpMjAxOSA8LSBwbHlyOjpyZW5hbWUoZGllbXRoaTIwMTksIGMoCiAgICAnc2JkJyA9ICdTdHVkZW50X2luZGV4JywKICAgICdUb2FuJz0gJ01hdGhzJywKICAgICdWYW4nID0gJ0xpdGVyYXR1cmUnLAogICAgJ05nb2FpX25ndScgPSAnRm9yZWlnbl9sYW5ndWFnZScsCiAgICAnTWFfbW9uX25nb2FpX25ndScgPSAnRm9yZWlnbl9sYW5ndWFnZV9jb2RlJywKICAgICdMaScgPSAnUGh5c2ljcycsCiAgICAnSG9hJyA9ICdDaGVtaXN0cnknLAogICAgJ1NpbmgnID0gJ0Jpb2xvZ3knLAogICAgJ1N1JyA9ICdIaXN0b3J5JywKICAgICdEaWEnID0gJ0dlb2dyYXBoeScsCiAgICAnR0RDRCcgPSAnQ2l0aXplbnNoaXBfZWR1Y2F0aW9uJwogICAgKQogICkKaGVhZChkaWVtdGhpMjAxOSkKYGBgCgpgYGB7cn0KI0luc2VydCBwcm92aW5jZV9jb2RlIGZvciBkaWVtdGhpMjAxOS5jc3YKUHJvdmluY2VfY29kZSA8LSBpZmVsc2UoZGllbXRoaTIwMTkkU3R1ZGVudF9pbmRleCA+IDEwMDAwMDAwLAogICAgICAgICAgICBzdWJzdHIoYXMuY2hhcmFjdGVyKGRpZW10aGkyMDE5JFN0dWRlbnRfaW5kZXgpLCBzdGFydCA9IDEsIHN0b3AgPSAyKSwKICAgICAgICAgICAgc3Vic3RyKGFzLmNoYXJhY3RlcihkaWVtdGhpMjAxOSRTdHVkZW50X2luZGV4KSwgc3RhcnQgPSAxLCBzdG9wID0gMSkKKQpkaWVtdGhpMjAxOSRQcm92aW5jZV9jb2RlIDwtIGFzLm51bWVyaWMoUHJvdmluY2VfY29kZSkKCiNpbnNlcnQgZm9yZWlnbiBsYW5ndWFnZSBuYW1lcyB3aXRoIHJlc3BlY3QgdG8gY29kZQpkaWVtdGhpMjAxOSRGb3JlaWduX2xhbmd1YWdlX25hbWUgPC0gZGllbXRoaTIwMTkkRm9yZWlnbl9sYW5ndWFnZV9jb2RlCmRpZW10aGkyMDE5JEZvcmVpZ25fbGFuZ3VhZ2VfbmFtZSA8LSBtYXB2YWx1ZXMoZGllbXRoaTIwMTkkRm9yZWlnbl9sYW5ndWFnZV9jb2RlLCBmcm9tPWMoIk4xIiwgIk4yIiwgIk4zIiwgIk40IiwgIk41IiwgIk42IiksIHRvPWMoIkVuZ2xpc2giLCAiUnVzc2lhbiIsICJGcmVuY2giLCAiQ2hpbmVzZSIsICJHZXJtYW4iLCAiSmFwYW5lc2UiKSkKCmhlYWQoZGllbXRoaTIwMTkpCmBgYAoKYGBge3J9CiNNZXJnZSBkaWVtdGhpMjAxOS5jc3YgYW5kIHByb3ZpbmNlX2NvZGUuY3N2CmRpZW10aGkyMDE5IDwtIGpvaW4oZGllbXRoaTIwMTksIHByb3ZpbmNlX2NvZGUsIGJ5ID0gIlByb3ZpbmNlX2NvZGUiKQpoZWFkKGRpZW10aGkyMDE5KQpgYGAKCgpgYGB7cn0KI0NhbGN1bGF0ZSBzY29yZXMgb2YgY29tYmluYXRpb25zIEEwMCwgQTAxLCBCMDAsIEMwMCwgRDAwCmRpZW10aGkyMDE5JEEwMCA8LSBkaWVtdGhpMjAxOSRNYXRocyArIGRpZW10aGkyMDE5JFBoeXNpY3MgKyBkaWVtdGhpMjAxOSRDaGVtaXN0cnkKaWYoZGllbXRoaTIwMTkkRm9yZWlnbl9sYW5ndWFnZV9jb2RlID09ICdOMScpIHsKICBkaWVtdGhpMjAxOSRBMDEgPC0gZGllbXRoaTIwMTkkTWF0aHMgKyBkaWVtdGhpMjAxOSRQaHlzaWNzICsgZGllbXRoaTIwMTkkRm9yZWlnbl9sYW5ndWFnZQp9CmRpZW10aGkyMDE5JEIwMCA8LSBkaWVtdGhpMjAxOSRNYXRocyArIGRpZW10aGkyMDE5JENoZW1pc3RyeSArIGRpZW10aGkyMDE5JEJpb2xvZ3kKZGllbXRoaTIwMTkkQzAwIDwtIGRpZW10aGkyMDE5JExpdGVyYXR1cmUgKyBkaWVtdGhpMjAxOSRIaXN0b3J5ICsgZGllbXRoaTIwMTkkR2VvZ3JhcGh5CmlmKGRpZW10aGkyMDE5JEZvcmVpZ25fbGFuZ3VhZ2VfY29kZSA9PSAnTjEnKSB7CiAgZGllbXRoaTIwMTkkRDAwIDwtIGRpZW10aGkyMDE5JE1hdGhzICsgZGllbXRoaTIwMTkkTGl0ZXJhdHVyZSArIGRpZW10aGkyMDE5JEZvcmVpZ25fbGFuZ3VhZ2UKfQpoZWFkKGRpZW10aGkyMDE5KQoKI0NhbGN1bGF0ZSBhdmVyYWdlIG9mIG5hdHVyYWwgc2NpZW5jZSBjb21iaW5hdGlvbiBhbmQgc29jaWFsIHNjaWVuY2UgY29tYmluYXRpb24KZGllbXRoaTIwMTkkQXZnX25hdHVyYWxfc2NpZW5jZXMgPC0gKGRpZW10aGkyMDE5JFBoeXNpY3MgKyBkaWVtdGhpMjAxOSRDaGVtaXN0cnkgKyBkaWVtdGhpMjAxOSRCaW9sb2d5KS8zCmRpZW10aGkyMDE5JEF2Z19zb2NpYWxfc2NpZW5jZXMgPC0gKGRpZW10aGkyMDE5JEhpc3RvcnkgKyBkaWVtdGhpMjAxOSRHZW9ncmFwaHkgKyBkaWVtdGhpMjAxOSRDaXRpemVuc2hpcF9lZHVjYXRpb24pLzMKYGBgCgpgYGB7cn0KI1Jlb3JkZXIgYW5kIGNob29zZSBuZWNlc3NhcnkgY29sdW1ucwpkaWVtdGhpMjAxOSA8LSBkaWVtdGhpMjAxOVtjKCdTdHVkZW50X2luZGV4JywgJ1Byb3ZpbmNlX2NvZGUnLCAnUHJvdmluY2VfbmFtZScsICdNYXRocycsICdMaXRlcmF0dXJlJywgJ0ZvcmVpZ25fbGFuZ3VhZ2UnICwnRm9yZWlnbl9sYW5ndWFnZV9jb2RlJywgJ0ZvcmVpZ25fbGFuZ3VhZ2VfbmFtZScsICdQaHlzaWNzJywgJ0NoZW1pc3RyeScsICdCaW9sb2d5JywgJ0F2Z19uYXR1cmFsX3NjaWVuY2VzJywgJ0hpc3RvcnknLCAnR2VvZ3JhcGh5JywgJ0NpdGl6ZW5zaGlwX2VkdWNhdGlvbicsICdBdmdfc29jaWFsX3NjaWVuY2VzJywgJ0EwMCcsICdBMDEnLCAnQjAwJywgJ0MwMCcsICdEMDAnKV0KaGVhZChkaWVtdGhpMjAxOSkKYGBgCgoKYGBge3J9CiNudW1lcmljYWwgZGYgZm9yIGNvcnJlbGF0aW9uIG1hdHJpeApkaWVtdGhpMjAxOV9jb3JyIDwtIGRpZW10aGkyMDE5W2MoNDo2LDk6MjEpXQoKI2NvcnJlbGF0aW9uIG1hdHJpeApkaWVtdGhpMjAxOV9jb3JyX21hdHJpeCA8LSBjb3IoZGllbXRoaTIwMTlfY29yciwgdXNlPSJwYWlyd2lzZS5jb21wbGV0ZS5vYnMiKQpWaWV3KGRpZW10aGkyMDE5X2NvcnJfbWF0cml4KQoKI2NvcnJlbGF0aW9uIGhlYXRtYXAKZ2djb3JycGxvdChkaWVtdGhpMjAxOV9jb3JyX21hdHJpeCwgaGMub3JkZXIgPSBUUlVFLAogICBsYWIgPSBUUlVFKQpgYGAKCmBgYHtyfQojTnVtYmVyIG9mIHN0dWRlbnRzIHdobyB0YWtlcyBlYWNoIGZvcmVpZ24gbGFuZ3VhZ2UgdGVzdAp0YWJsZShkaWVtdGhpMjAxOSRGb3JlaWduX2xhbmd1YWdlX25hbWUpCmBgYAoKYGBge3J9CiNOdW1iZXIgb2Ygc3R1ZGVudHMgd2hvIHRvb2sgZWFjaCBzdWJqZWN0CnRvb2tfc3ViamVjdCA8LSBsaXN0KCkKZm9yKGkgaW4gYyg0OjYsIDk6MTEsIDEzOjE1KSkgewogIHByaW50KHBhc3RlKCdUaGUgbnVtYmVyIG9mIHN0dWRlbnRzIHdobyB0b29rIHRoZSBzdWJqZWN0JywgY29sbmFtZXMoZGllbXRoaTIwMTlbaV0pLCAnaXMnLCBzdW0oIWlzLm5hKGRpZW10aGkyMDE5WyxpXSkgPT0gVFJVRSkpKSAKfQpgYGAKCmBgYHtyfQojTnVtYmVyIG9mIHN0dWRlbnRzIHdobyBhcmUgZWxpZ2libGUgdG8gYmUgY29uc2lkZXJlZCBmb3IgYWRtaXNzaW9uIHdpdGggZWFjaCBjb21iaW5hdGlvbiBBMDAsIEEwMSwgQjAwLCBDMDAsIEQwMApjb21iaW5hdGlvbl9lbGlnaWJsZSA8LSBsaXN0KCkKZm9yKGkgaW4gYygxNzoyMSkpIHsKICBwcmludChwYXN0ZSgnVGhlIG51bWJlciBvZiBzdHVkZW50cyB3aG8gYXJlIGVsaWdpYmxlIHRvIGJlIGNvbnNpZGVyZWQgZm9yIGNvbWJpbmF0aW9uJywgY29sbmFtZXMoZGllbXRoaTIwMTlbaV0pLCAnaXMnLCBzdW0oIWlzLm5hKGRpZW10aGkyMDE5WyxpXSkgPT0gVFJVRSkpKSAKICBjb21iaW5hdGlvbl9lbGlnaWJsZVtbaS0xNl1dID0gdGFibGUoIWlzLm5hKGRpZW10aGkyMDE5WyxpXSksIGRubiA9IHBhc3RlKGNvbG5hbWVzKGRpZW10aGkyMDE5KVtpXSkpCn0KY29tYmluYXRpb25fZWxpZ2libGUKYGBgCgpgYGB7cn0KI051bWJlciBvZiBzdHVkZW50cyB3aG8gdG9vayBhbGwgbmF0dXJhbCBzY2llbmNlIHN1YmplY3RzLCBhbGwgc29jaWFsIHNjaWVuY2Ugc3ViamVjdHMsIG9yIGFsbCBvZiBib3RoCnByaW50KHBhc3RlKCdUaGUgbnVtYmVyIG9mIHN0dWRlbnRzIHdobyB0b29rIGFsbCBuYXR1cmFsIHNjaWVuY2Ugc3ViamVjdHMgaXMnLCBzdW0oIWlzLm5hKGRpZW10aGkyMDE5WywxM10pID09IFRSVUUpKSkKcHJpbnQocGFzdGUoJ1RoZSBudW1iZXIgb2Ygc3R1ZGVudHMgd2hvIHRvb2sgYWxsIHNvY2lhbCBzY2llbmNlIHN1YmplY3RzIGlzJywgc3VtKCFpcy5uYShkaWVtdGhpMjAxOVssMTddKSA9PSBUUlVFKSkpCnByaW50KHBhc3RlKCdUaGUgbnVtYmVyIG9mIHN0dWRlbnRzIHdobyB0b29rIGFsbCBuYXR1cmFsIGFuZCBzb2NpYWwgc2NpZW5jZSBzdWJqZWN0cyBpcycsIHN1bSghaXMubmEoZGllbXRoaTIwMTlbLDEzXSkgPT0gVFJVRSAmICFpcy5uYShkaWVtdGhpMjAxOVssMTddKSA9PSBUUlVFKSkpCmBgYAoKCmBgYHtyfQojRmluZCB0aGUgbWF4aW11bSBzY29yZSBmb3IgZWFjaCBjb2x1bW4KZm9yKGkgaW4gYyg0OjYsOToyMSkpIHsKICBwcmludChwYXN0ZSgnVGhlIG1heGltdW0gc2NvcmUgb2YnLGNvbG5hbWVzKGRpZW10aGkyMDE5KVtpXSwnaXMnLCBtYXgoZGllbXRoaTIwMTlbLGldLCBuYS5ybSA9IFRSVUUpKSkKfQpgYGAKCmBgYHtyfQpoaXN0b2dyYW1fb3V0IDwtIGxpc3QoKQpmb3IoaSBpbiBjKDQ6Niw5OjIxKSkgewogIHggPSBkaWVtdGhpMjAxOVssaV0KICBoaXN0b2dyYW1fb3V0W1tpXV0gPC0gZ2dwbG90KGRhdGEuZnJhbWUoeCksIGFlcyh4KSkgKyAKICAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4xLCBjb2xvcj0iYmxhY2siLCBmaWxsPSJibHVlIikgKwogICAgbGFicyh0aXRsZT1wYXN0ZSgiU2NvcmUgaGlzdG9ncmFtIGZvciIsY29sbmFtZXMoZGllbXRoaTIwMTkpW2ldKSwgeD1jb2xuYW1lcyhkaWVtdGhpMjAxOSlbaV0sIHk9IkNvdW50IikgKyAKICAgIGdlb21fdmxpbmUoZGF0YSA9IGRpZW10aGkyMDE5LCB4aW50ZXJjZXB0ID0gbWVhbihkaWVtdGhpMjAxOVssaV0sIG5hLnJtID0gVFJVRSksIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAxKQp9Cmhpc3RvZ3JhbV9vdXQKYGBgCgpgYGB7cn0KdGFibGVfc2NvcmUgPC0gbGlzdCgpCmZvcihpIGluIGMoNDo2LDk6MjEpKSB7CiAgdGFibGVfc2NvcmVbW2ldXSA9IHRhYmxlKGRpZW10aGkyMDE5WyxpXSwgZG5uID0gcGFzdGUoY29sbmFtZXMoZGllbXRoaTIwMTkpW2ldLCdfc2NvcmVzJykpCn0KCmZvcihpIGluIGMoNDo2LDk6MjEpKSB7CiAgVmlldyh0YWJsZV9zY29yZVtbaV1dKQp9CiN0YWJsZV9zY29yZQpgYGAKCmBgYHtyfQpzdW1tYXJ5KGRpZW10aGkyMDE5WywzXSkKYGBgCgpgYGB7cn0KcHJvdmluY2VfZnJlcXVlbmN5IDwtIHRhYmxlKGRpZW10aGkyMDE5WywzXSkKICNzb3J0KHByb3ZpbmNlX2ZyZXF1ZW5jeSwgZGVjcmVhc2luZyA9IEZBTFNFKSAKcHJvdmluY2VfZnJlcXVlbmN5IDwtY291bnQoZGllbXRoaTIwMTksIFByb3ZpbmNlX25hbWUpCm5hbWVzKHByb3ZpbmNlX2ZyZXF1ZW5jeSkgPC0gYygnUHJvdmluY2UnLCAnRnJlcXVlbmN5JykKcHJvdmluY2VfZnJlcXVlbmN5IDwtIHByb3ZpbmNlX2ZyZXF1ZW5jeVtvcmRlcigtcHJvdmluY2VfZnJlcXVlbmN5JEZyZXF1ZW5jeSksXQpwYXIobGFzPTIpClZpZXcocHJvdmluY2VfZnJlcXVlbmN5KQoKZ2dwbG90KGRhdGE9cHJvdmluY2VfZnJlcXVlbmN5LCBhZXMoeD1yZW9yZGVyKFByb3ZpbmNlLEZyZXF1ZW5jeSkseT1GcmVxdWVuY3kpKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIiwgc3RhdD0iaWRlbnRpdHkiKSArIAogIGNvb3JkX2ZsaXAoKSArCiAgZ2d0aXRsZShwYXN0ZSgnQmFycGxvdCBvZiBudW1iZXIgb2Ygc3R1ZGVudHMgYnkgcHJvdmluY2UnKSkgKwogIGxhYnMoeCA9ICJQcm92aW5jZSIsIHkgPSAiTnVtYmVyIG9mIHN0dWRlbnRzIikKYGBgCgoKYGBge3J9CmJhcnBsb3RfbWVhbiA8LSBsaXN0KCkKZm9yKGkgaW4gYyg0OjYsOToyMSkpIHsKICB4IDwtIGFnZ3JlZ2F0ZShkaWVtdGhpMjAxOVssaV0gfiBkaWVtdGhpMjAxOSRQcm92aW5jZV9uYW1lLCBkaWVtdGhpMjAxOSwgbWVhbikKICBuYW1lcyh4KSA8LSBjKCdQcm92aW5jZScsICdNZWFuJykKICB4IDwtIHhbb3JkZXIoeCRNZWFuKSxdCiAgCiAgYmFycGxvdF9tZWFuW1tpXV0gPC0gZ2dwbG90KGRhdGE9eCwgYWVzKHg9cmVvcmRlcihQcm92aW5jZSxNZWFuKSx5PU1lYW4pKSArCiAgZ2VvbV9iYXIocG9zaXRpb249ImRvZGdlIixzdGF0PSJpZGVudGl0eSIpICsgCiAgY29vcmRfZmxpcCgpICsKICBnZ3RpdGxlKHBhc3RlKCdCYXJwbG90IGZvciBtZWFuIG9mJywgY29sbmFtZXMoZGllbXRoaTIwMTkpW2ldLCAnYnkgcHJvdmluY2UnKSkgKyAKICBsYWJzKHggPSAiUHJvdmluY2UiLCB5ID0gIk1lYW4gc2NvcmUiKQp9CmJhcnBsb3RfbWVhbgpgYGAKCgoK